package ar.com.spsolutions.splibrary.notifiers;

import java.util.HashSet;
import java.util.Properties;
import java.util.Set;

import javax.mail.Message;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

import ar.com.spsolutions.splibrary.notifiers.exception.NotifierException;
import ar.com.spsolutions.splibrary.user.User;

/**
 * @author leezsi
 * 
 */
public class EmailNotifier implements INotifier {

	private static final long serialVersionUID = 7820450925266679746L;

	private String message;

	private String subject;
	private boolean dummy;
	private String debug;
	private String user;
	private String password;
	private String transport;

	private String host;
	private String tls;
	private String port;
	private String authorization;

	private transient Set<User> recipients;

	@Override
	public void setMessage(final String mailMessage) {
		this.message = mailMessage;
	}

	public String getMessage() {
		return this.message;
	}

	@Override
	public void setSubject(final String subject) {
		this.subject = subject;
	}

	public String getSubject() {
		return this.subject;
	}

	@Override
	public void setRecipients(final Set<User> users) {
		this.recipients = users;
	}

	public Set<User> getRecipients() {
		return this.recipients;
	}

	@Override
	public void sendNotification() {
		if (!this.isDummy()) {
			final Session session = Session.getDefaultInstance(this
					.getProperties());
			final MimeMessage mail = this.createMail(session);
			this.sendMail(session, mail);
		}
	}

	private Properties getProperties() {
		final Properties properties = new Properties();
		properties.put("mail.smtp.host", this.getHost());
		properties.put("mail.smtp.starttls.enable", this.getTls());
		properties.put("mail.smtp.port", this.getPort());
		properties.put("mail.smtp.auth", this.getAuthorization());
		properties.put("mail.debug", this.getDebug());
		return properties;
	}

	private void sendMail(final Session session, final MimeMessage mail) {
		Transport transportProtocol;
		try {
			transportProtocol = session.getTransport(this.getTransport());
			transportProtocol.connect(this.getUser(), this.getPassword());
			transportProtocol.sendMessage(mail, mail.getAllRecipients());
			transportProtocol.close();
		} catch (final Exception e) {
			throw new NotifierException(e);
		}
	}

	private MimeMessage createMail(final Session session) {
		final MimeMessage mail = new MimeMessage(session);
		try {
			mail.setFrom(new InternetAddress(this.getUser()));
			for (final User recipient : this.getRecipients()) {
				mail.addRecipient(Message.RecipientType.TO,
						this.getAddresFor(recipient));
			}
			mail.setSubject(this.getSubject());
			mail.setText(this.getMessage());
			return mail;
		} catch (final Exception e) {
			throw new NotifierException(e);
		}
	}

	private InternetAddress getAddresFor(final User recipient)
			throws AddressException {
		return new InternetAddress(recipient.getEmail());
	}

	@Override
	public void setRecipient(final User aUser) {
		final Set<User> tempReceivers = new HashSet<User>();
		tempReceivers.add(aUser);
		this.setRecipients(tempReceivers);
	}

	public String getUser() {
		return this.user;
	}

	public void setUser(final String user) {
		this.user = user;
	}

	public String getPassword() {
		return this.password;
	}

	public void setPassword(final String password) {
		this.password = password;
	}

	public String getTransport() {
		return this.transport;
	}

	public void setTransport(final String transport) {
		this.transport = transport;
	}

	public String getHost() {
		return this.host;
	}

	public void setHost(final String host) {
		this.host = host;
	}

	public boolean isDummy() {
		return this.dummy;
	}

	public void setDummy(final boolean dummy) {
		this.dummy = dummy;
	}

	public String getDebug() {
		return this.debug;
	}

	public void setDebug(final String debug) {
		this.debug = debug;
	}

	public String getTls() {
		return this.tls;
	}

	public void setTls(final String tls) {
		this.tls = tls;
	}

	public String getPort() {
		return this.port;
	}

	public void setPort(final String port) {
		this.port = port;
	}

	public String getAuthorization() {
		return this.authorization;
	}

	public void setAuthorization(final String authorization) {
		this.authorization = authorization;
	}

}
